#ifndef SQL_PARSER_H
#define SQL_PARSER_H

#include "../../include/gudb.h"
#include <stdint.h>
#include <stdbool.h>

// Token types
typedef enum {
    TOKEN_INVALID = 0,
    TOKEN_EOF,
    TOKEN_IDENTIFIER,
    TOKEN_STRING,
    TOKEN_NUMBER,
    TOKEN_KEYWORD,
    TOKEN_OPERATOR,
    TOKEN_PUNCTUATION,
    
    // Keywords
    TOKEN_SELECT,
    TOKEN_FROM,
    TOKEN_WHERE,
    TOKEN_INSERT,
    TOKEN_INTO,
    TOKEN_VALUES,
    TOKEN_UPDATE,
    TOKEN_SET,
    TOKEN_DELETE,
    TOKEN_CREATE,
    TOKEN_TABLE,
    TOKEN_VIEW,
    TOKEN_DROP,
    TOKEN_ALTER,
    TOKEN_GRANT,
    TOKEN_REVOKE,
    TOKEN_USER,
    TOKEN_AND,
    TOKEN_OR,
    TOKEN_NOT,
    TOKEN_IN,
    TOKEN_IF,
    TOKEN_LIKE,
    TOKEN_ORDER,
    TOKEN_BY,
    TOKEN_GROUP,
    TOKEN_HAVING,
    TOKEN_COUNT,
    TOKEN_SUM,
    TOKEN_AVG,
    TOKEN_MIN,
    TOKEN_MAX,
    TOKEN_LIMIT,
    TOKEN_OFFSET,
    TOKEN_JOIN,
    TOKEN_LEFT,
    TOKEN_RIGHT,
    TOKEN_INNER,
    TOKEN_OUTER,
    TOKEN_ON,
    TOKEN_AS,
    TOKEN_ASC,
    TOKEN_DESC,
    TOKEN_DISTINCT,
    TOKEN_ALL,
    TOKEN_UNION,
    TOKEN_INTERSECT,
    TOKEN_EXCEPT,
    TOKEN_EXISTS,
    TOKEN_BETWEEN,
    TOKEN_IS,
    TOKEN_NULL,
    TOKEN_TRUE,
    TOKEN_FALSE,
    TOKEN_PRIMARY,
    TOKEN_KEY,
    TOKEN_FOREIGN,
    TOKEN_REFERENCES,
    TOKEN_UNIQUE,
    TOKEN_INDEX,
    TOKEN_DEFAULT,
    TOKEN_AUTO_INCREMENT,
    TOKEN_PARTITION,
    TOKEN_RANGE,
    TOKEN_HASH,
    TOKEN_LESS,
    TOKEN_THAN,
    TOKEN_ENGINE,
    TOKEN_ENCRYPTED,
    TOKEN_YES,
    TOKEN_IDENTIFIED,
    TOKEN_PASSWORD,
    TOKEN_START,
    TOKEN_TRANSACTION,
    TOKEN_COMMIT,
    TOKEN_ROLLBACK,
    TOKEN_ANALYZE,
    TOKEN_DESCRIBE,
    TOKEN_SHOW,
    TOKEN_USE,
    TOKEN_COLUMNS,
    TOKEN_STATUS,
    TOKEN_DATABASE,
    TOKEN_TRIGGER,
    TOKEN_BEFORE,
    TOKEN_AFTER,
    TOKEN_INSTEAD,
    TOKEN_WHEN,
    TOKEN_FOR,
    TOKEN_EACH,
    TOKEN_ROW,
    
    // Data types
    TOKEN_TINYINT,
    TOKEN_INT,
    TOKEN_BIGINT,
    TOKEN_FLOAT,
    TOKEN_DOUBLE,
    TOKEN_CHAR,
    TOKEN_VARCHAR,
    TOKEN_TEXT,
    TOKEN_JSON,
    TOKEN_DATE,
    TOKEN_DATETIME,
    TOKEN_TIMESTAMP,
    
    // Operators
    TOKEN_EQUAL,        // =
    TOKEN_NOT_EQUAL,    // !=, <>
    TOKEN_LESS_THAN,    // <
    TOKEN_LESS_EQUAL,   // <=
    TOKEN_GREATER_THAN, // >
    TOKEN_GREATER_EQUAL,// >=
    TOKEN_PLUS,         // +
    TOKEN_MINUS,        // -
    TOKEN_MULTIPLY,     // *
    TOKEN_DIVIDE,       // /
    TOKEN_MODULO,       // %
    TOKEN_ASSIGN,       // :=
    
    // Punctuation
    TOKEN_SEMICOLON,    // ;
    TOKEN_COMMA,        // ,
    TOKEN_DOT,          // .
    TOKEN_LPAREN,       // (
    TOKEN_RPAREN,       // )
    TOKEN_LBRACE,       // {
    TOKEN_RBRACE,       // }
    TOKEN_LBRACKET,     // [
    TOKEN_RBRACKET,     // ]
    TOKEN_QUESTION,     // ?
    TOKEN_AT,           // @
    TOKEN_DOLLAR,       // $
} token_type_t;

// SQL statement types
typedef enum {
    STMT_INVALID = 0,
    STMT_SELECT,
    STMT_INSERT,
    STMT_UPDATE,
    STMT_DELETE,
    STMT_CREATE_TABLE,
    STMT_CREATE_DATABASE,
    STMT_CREATE_USER,
    STMT_CREATE_VIEW,
    STMT_CREATE_INDEX,
    STMT_DROP_TABLE,
    STMT_DROP_DATABASE,
    STMT_DROP_USER,
    STMT_DROP_VIEW,
    STMT_DROP_INDEX,
    STMT_ALTER_TABLE,
    STMT_GRANT,
    STMT_REVOKE,
    STMT_START_TRANSACTION,
    STMT_COMMIT,
    STMT_ROLLBACK,
    STMT_ANALYZE,
    STMT_USE,
    STMT_DESCRIBE,
    STMT_SHOW_DATABASES,
    STMT_SHOW_TABLES,
    STMT_SHOW_COLUMNS,
    STMT_SHOW_CREATE_TABLE,
    STMT_SHOW_STATUS,
    STMT_CREATE_TRIGGER,
    STMT_DROP_TRIGGER
} stmt_type_t;

// Expression types
typedef enum {
    EXPR_INVALID = 0,
    EXPR_COLUMN,
    EXPR_LITERAL,
    EXPR_BINARY_OP,
    EXPR_UNARY_OP,
    EXPR_FUNCTION_CALL,
    EXPR_CASE,
    EXPR_SUBQUERY,
    EXPR_LIST,
    EXPR_STAR  // SELECT *
} expr_type_t;

// Data types
typedef enum {
    DATA_TYPE_INVALID = 0,
    DATA_TYPE_TINYINT,
    DATA_TYPE_INT,
    DATA_TYPE_BIGINT,
    DATA_TYPE_FLOAT,
    DATA_TYPE_DOUBLE,
    DATA_TYPE_CHAR,
    DATA_TYPE_VARCHAR,
    DATA_TYPE_TEXT,
    DATA_TYPE_JSON,
    DATA_TYPE_DATE,
    DATA_TYPE_DATETIME,
    DATA_TYPE_TIMESTAMP
} data_type_t;

// Sort direction for ORDER BY
typedef enum {
    SORT_ASC = 0,
    SORT_DESC
} sort_direction_t;

// Forward declarations
typedef struct token token_t;
typedef struct expression expression_t;
typedef struct statement statement_t;
typedef struct column_def column_def_t;
typedef struct table_ref table_ref_t;
typedef struct order_by_item order_by_item_t;

// Token structure
struct token {
    token_type_t type;
    char* value;
    uint32_t length;
    uint32_t line;
    uint32_t column;
    struct token* next;
};

// Expression structure
struct expression {
    expr_type_t type;
    data_type_t data_type;
    
    union {
        struct {
            char* table_name;
            char* column_name;
        } column;
        
        struct {
            char* value;
            uint32_t length;
        } literal;
        
        struct {
            token_type_t operator;
            expression_t* left;
            expression_t* right;
        } binary_op;
        
        struct {
            token_type_t operator;
            expression_t* operand;
        } unary_op;
        
        struct {
            char* function_name;
            expression_t** args;
            uint32_t arg_count;
        } function_call;
        
        struct {
            expression_t** expressions;
            uint32_t count;
        } list;
        
        struct {
            statement_t* query;          // The subquery statement
            bool is_correlated;          // Whether subquery references outer query
            char** correlation_refs;     // Names of outer columns referenced
            uint32_t correlation_count;  // Number of outer references
        } subquery;
    } data;
    
    struct expression* next;
};

// Column definition for CREATE TABLE
struct column_def {
    char* name;
    data_type_t type;
    uint32_t length;        // For VARCHAR, CHAR
    bool not_null;
    bool primary_key;
    bool unique;
    bool auto_increment;
    char* default_value;
    
    struct column_def* next;
};

// Table reference for FROM clause
struct table_ref {
    char* table_name;
    char* alias;
    expression_t* join_condition;
    token_type_t join_type;
    
    struct table_ref* next;
};

// ORDER BY item structure
struct order_by_item {
    expression_t* expression;        // The expression to sort by
    sort_direction_t direction;      // ASC or DESC
    
    struct order_by_item* next;      // Next item in ORDER BY list
};

// SQL statement structure
struct statement {
    stmt_type_t type;
    uint32_t line;
    uint32_t column;
    
    union {
        // SELECT statement
        struct {
            expression_t* select_list;
            table_ref_t* from_list;
            expression_t* where_clause;
            expression_t* group_by;
            expression_t* having;
            order_by_item_t* order_by;
            bool distinct;
            uint32_t limit;
            uint32_t offset;
        } select;
        
        // INSERT statement
        struct {
            char* table_name;
            char** column_names;
            uint32_t column_count;
            expression_t** values;
            uint32_t value_count;
        } insert;
        
        // UPDATE statement
        struct {
            char* table_name;
            expression_t** assignments;
            uint32_t assignment_count;
            expression_t* where_clause;
        } update;
        
        // DELETE statement
        struct {
            char* table_name;
            expression_t* where_clause;
        } delete;
        
        // CREATE TABLE statement
        struct {
            char* table_name;
            column_def_t* columns;
            char* engine;
            bool encrypted;
            char* partition_type;  // "range" or "hash"
            char* partition_key;
        } create_table;
        
        // CREATE DATABASE statement
        struct {
            char* database_name;
            bool if_not_exists;
        } create_database;
        
        // CREATE USER statement
        struct {
            char* username;
            char* password;
            char* role;
        } create_user;
        
        // CREATE VIEW statement
        struct {
            char* view_name;
            expression_t* select_list;
            table_ref_t* from_list;
            expression_t* where_clause;
            expression_t* group_by;
            expression_t* having;
            order_by_item_t* order_by;
            bool or_replace;
        } create_view;
        
        // CREATE INDEX statement
        struct {
            char* index_name;
            char* table_name;
            char** column_names;
            uint32_t column_count;
            bool unique;
            bool if_not_exists;
        } create_index;
        
        // DROP INDEX statement
        struct {
            char* index_name;
            char* table_name;      // Optional - some DBs require it
            bool if_exists;
        } drop_index;
        
        // DROP VIEW statement
        struct {
            char* view_name;
            bool if_exists;
            bool cascade;
        } drop_view;
        
        // DROP TABLE statement
        struct {
            char* table_name;
            bool if_exists;
            bool cascade;
        } drop_table;
        
        // DROP DATABASE statement
        struct {
            char* database_name;
            bool if_exists;
        } drop_database;
        
        // ALTER TABLE statement
        struct {
            char* table_name;
            enum {
                ALTER_ADD_COLUMN = 1,
                ALTER_DROP_COLUMN,
                ALTER_MODIFY_COLUMN,
                ALTER_RENAME_COLUMN,
                ALTER_ADD_INDEX,
                ALTER_DROP_INDEX
            } operation;
            char* column_name;
            char* new_column_name;     // For RENAME COLUMN
            data_type_t column_type;
            uint32_t column_length;
            bool not_null;
            bool primary_key;
            bool unique;
            char* default_value;
            char* index_name;          // For ADD/DROP INDEX
        } alter_table;
        
        // GRANT statement
        struct {
            uint8_t permissions;  // Bitmask of permissions
            char* table_name;
            char* username;
        } grant;
        
        // Transaction statements
        struct {
            uint8_t isolation_level;
        } transaction;
        
        // USE statement
        struct {
            char* database_name;
        } use;
        
        // DESCRIBE statement
        struct {
            char* table_name;
        } describe;
        
        // SHOW statements
        struct {
            char* table_name;  // For SHOW CREATE TABLE, SHOW COLUMNS FROM
            char* database_name;  // For SHOW TABLES
        } show;
        
        // CREATE TRIGGER statement
        struct {
            char* trigger_name;
            char* table_name;
            uint8_t timing;      // TRIGGER_TIMING_BEFORE/AFTER/INSTEAD_OF
            uint8_t events;      // Bitmask of TRIGGER_EVENT_*
            char* condition;     // WHEN condition (optional)
            char* action_sql;    // SQL statements to execute
            bool or_replace;
            bool for_each_row;   // FOR EACH ROW vs FOR EACH STATEMENT
        } create_trigger;
        
        // DROP TRIGGER statement
        struct {
            char* trigger_name;
            char* table_name;    // Optional - some DBs require it
            bool if_exists;
        } drop_trigger;
    } data;
};

// Lexer structure
typedef struct {
    const char* input;
    uint32_t position;
    uint32_t length;
    uint32_t line;
    uint32_t column;
    token_t* current_token;
    char* error_message;
} lexer_t;

// Parser structure
typedef struct {
    lexer_t* lexer;
    token_t* current_token;
    char* error_message;
    uint32_t error_line;
    uint32_t error_column;
} parser_t;

// SQL Parser API
parser_t* parser_create(const char* sql);
void parser_destroy(parser_t* parser);

// Parse functions
statement_t* parser_parse_statement(parser_t* parser);
expression_t* parser_parse_expression(parser_t* parser);

// Statement parsing functions
statement_t* parser_parse_select(parser_t* parser);
statement_t* parser_parse_insert(parser_t* parser);
statement_t* parser_parse_update(parser_t* parser);
statement_t* parser_parse_delete(parser_t* parser);
statement_t* parser_parse_create_table(parser_t* parser);
statement_t* parser_parse_create_database(parser_t* parser);
statement_t* parser_parse_create_user(parser_t* parser);
statement_t* parser_parse_create_view(parser_t* parser);
statement_t* parser_parse_create_index(parser_t* parser);
statement_t* parser_parse_drop_index(parser_t* parser);
statement_t* parser_parse_drop_view(parser_t* parser);
statement_t* parser_parse_drop_table(parser_t* parser);
statement_t* parser_parse_drop_database(parser_t* parser);
statement_t* parser_parse_alter_table(parser_t* parser);
statement_t* parser_parse_grant(parser_t* parser);
statement_t* parser_parse_transaction(parser_t* parser);
statement_t* parser_parse_use(parser_t* parser);
statement_t* parser_parse_describe(parser_t* parser);
statement_t* parser_parse_show(parser_t* parser);
statement_t* parser_parse_create_trigger(parser_t* parser);
statement_t* parser_parse_drop_trigger(parser_t* parser);

// Expression parsing functions
expression_t* parser_parse_or_expression(parser_t* parser);
expression_t* parser_parse_and_expression(parser_t* parser);
expression_t* parser_parse_equality_expression(parser_t* parser);
expression_t* parser_parse_relational_expression(parser_t* parser);
expression_t* parser_parse_additive_expression(parser_t* parser);
expression_t* parser_parse_multiplicative_expression(parser_t* parser);
expression_t* parser_parse_unary_expression(parser_t* parser);
expression_t* parser_parse_primary_expression(parser_t* parser);

// Lexer functions
lexer_t* lexer_create(const char* input);
void lexer_destroy(lexer_t* lexer);
token_t* lexer_next_token(lexer_t* lexer);
token_t* lexer_peek_token(lexer_t* lexer);

// Token functions
token_t* token_create(token_type_t type, const char* value, uint32_t length);
void token_destroy(token_t* token);
bool token_match(token_t* token, token_type_t type);
bool token_match_keyword(token_t* token, const char* keyword);

// Utility functions
const char* token_type_to_string(token_type_t type);
const char* stmt_type_to_string(stmt_type_t type);
const char* expr_type_to_string(expr_type_t type);
data_type_t string_to_data_type(const char* type_name);

// Enhanced SELECT list parsing
expression_t* parser_parse_select_list(parser_t* parser);
table_ref_t* parser_parse_from_clause(parser_t* parser);

// ORDER BY parsing
order_by_item_t* parser_parse_order_by_list(parser_t* parser);

// Expression list helper functions
bool expression_is_list(expression_t* expr);
uint32_t expression_get_count(expression_t* expr);
expression_t* expression_get_nth(expression_t* expr, uint32_t index);
const char* data_type_to_string(data_type_t type);

// Memory management
void statement_destroy(statement_t* stmt);
void expression_destroy(expression_t* expr);
void column_def_destroy(column_def_t* col);
void table_ref_destroy(table_ref_t* table);
void order_by_item_destroy(order_by_item_t* item);

// Error handling
bool parser_has_error(parser_t* parser);
const char* parser_get_error(parser_t* parser);
void parser_set_error(parser_t* parser, const char* message);

// Helper functions
bool is_keyword(const char* word);
token_type_t keyword_to_token_type(const char* keyword);
bool is_operator(char c);
bool is_whitespace(char c);
bool is_alpha(char c);
bool is_digit(char c);
bool is_alnum(char c);

// AST validation
bool validate_statement(statement_t* stmt);
bool validate_expression(expression_t* expr);

// SQL generation (for debugging)
char* statement_to_sql(statement_t* stmt);
char* expression_to_sql(expression_t* expr);

#endif // SQL_PARSER_H